using System.Data;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Xml;
using Chaotic.DataBase.DataAccess.Entity; 

namespace Chaotic.DataBase.DataAccess
{
	public abstract class AbstractDataAccess : IDataAccess, IDataStructure
	{
		public abstract DatabaseType DatabaseType { get; }

		public abstract IDbConnection DbConnection { get; }

		public bool IsClosed => DbConnection.State.Equals(ConnectionState.Closed);

		public string Owner { get; set; }

		public abstract IDbTransaction? BeginTransaction();

		public void Open()
		{
			if (DbConnection.State.Equals(ConnectionState.Closed))
			{
				DbConnection.Open();
			}
		}

		public virtual void Close()
		{
			DbConnection.Close();
		}

		public int ExecuteNonQuery(CommandType commandType, string? commandText)
		{
			return ExecuteNonQuery(commandType, commandText, null, null, null);
		}

		public int ExecuteNonQuery(string? commandText)
		{
			return ExecuteNonQuery(CommandType.Text, commandText, null, null, null);
		}

		public int ExecuteNonQuery(string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteNonQuery(CommandType.Text, commandText, commandParameters, null, null);
		}

		public int ExecuteNonQuery(DataRow row, SqlStruct sqlStruct)
		{
			QueryParameterCollection commandParameters = new QueryParameterCollection();
			return ExecuteNonQuery(CommandType.Text, null, commandParameters, row, sqlStruct);
		}

		public int ExecuteNonQuery(CommandType commandType, string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteNonQuery(commandType, commandText, commandParameters, null, null);
		}

		public abstract int ExecuteNonQuery(CommandType commandType, string? commandText, QueryParameterCollection commandParameters, DataRow row, SqlStruct sqlStruct);

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText)
		{
			return ExecuteDataset(commandType, commandText, null, new DataSet(), null);
		}

		public DataSet? ExecuteDataset(string? commandText)
		{
			return ExecuteDataset(CommandType.Text, commandText, null, new DataSet(), null);
		}

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteDataset(commandType, commandText, commandParameters, new DataSet(), null);
		}

		public DataSet? ExecuteDataset(string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteDataset(CommandType.Text, commandText, commandParameters, new DataSet(), null);
		}

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText, DataSet? ds)
		{
			return ExecuteDataset(commandType, commandText, null, ds, null);
		}

		public DataSet? ExecuteDataset(string? commandText, DataSet? ds)
		{
			return ExecuteDataset(CommandType.Text, commandText, null, ds, null);
		}

		public DataSet? ExecuteDataset(string? commandText, QueryParameterCollection commandParameters, DataSet? ds)
		{
			return ExecuteDataset(CommandType.Text, commandText, commandParameters, ds, null);
		}

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText, string tableName)
		{
			return ExecuteDataset(commandType, commandText, null, new DataSet(), tableName);
		}

		public DataSet? ExecuteDataset(string? commandText, string tableName)
		{
			return ExecuteDataset(CommandType.Text, commandText, null, new DataSet(), tableName);
		}

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText, QueryParameterCollection commandParameters, string tableName)
		{
			return ExecuteDataset(commandType, commandText, commandParameters, new DataSet(), tableName);
		}

		public DataSet? ExecuteDataset(string? commandText, QueryParameterCollection commandParameters, string tableName)
		{
			return ExecuteDataset(CommandType.Text, commandText, commandParameters, new DataSet(), tableName);
		}

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText, DataSet? ds, string tableName)
		{
			return ExecuteDataset(commandType, commandText, null, ds, tableName);
		}

		public DataSet? ExecuteDataset(string? commandText, DataSet? ds, string tableName)
		{
			return ExecuteDataset(CommandType.Text, commandText, null, ds, tableName);
		}

		public DataSet? ExecuteDataset(string? commandText, QueryParameterCollection commandParameters, DataSet? ds, string tableName)
		{
			return ExecuteDataset(CommandType.Text, commandText, commandParameters, ds, tableName);
		}

		public DataSet? ExecuteDataset(CommandType commandType, string? commandText, QueryParameterCollection commandParameters, DataSet? ds)
		{
			return ExecuteDataset(commandType, commandText, commandParameters, ds, null);
		}

		public abstract DataSet? ExecuteDataset(CommandType commandType, string? commandText, QueryParameterCollection commandParameters, DataSet? ds, string tableName);

		public abstract DataSet? ExecuteDataset(string? commandText, QueryParameterCollection commandParameters, DataSet? ds, int startRecord, int maxRecords, string tableName);

		public IDataReader ExecuteReader(CommandType commandType, string? commandText)
		{
			return ExecuteReader(commandType, commandText, null);
		}

		public IDataReader ExecuteReader(string? commandText)
		{
			return ExecuteReader(CommandType.Text, commandText, null);
		}

		public IDataReader ExecuteReader(string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteReader(CommandType.Text, commandText, commandParameters);
		}

		public abstract IDataReader ExecuteReader(CommandType commandType, string? commandText, QueryParameterCollection commandParameters);

		public object? ExecuteScalar(CommandType commandType, string? commandText)
		{
			return ExecuteScalar(commandType, commandText, null);
		}

		public object? ExecuteScalar(string? commandText)
		{
			return ExecuteScalar(CommandType.Text, commandText, null);
		}

		public object? ExecuteScalar(string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteScalar(CommandType.Text, commandText, commandParameters);
		}

		public abstract object? ExecuteScalar(CommandType commandType, string? commandText, QueryParameterCollection commandParameters);

		public XmlReader? ExecuteXmlReader(CommandType commandType, string? commandText)
		{
			return ExecuteXmlReader(commandType, commandText, null);
		}

		public XmlReader? ExecuteXmlReader(string? commandText)
		{
			return ExecuteXmlReader(CommandType.Text, commandText, null);
		}

		public XmlReader? ExecuteXmlReader(string? commandText, QueryParameterCollection commandParameters)
		{
			return ExecuteXmlReader(CommandType.Text, commandText, commandParameters);
		}

		public abstract XmlReader? ExecuteXmlReader(CommandType commandType, string? commandText, QueryParameterCollection commandParameters);

		protected void LogOutPut(Func<int> action, string type, string? commandText, QueryParameterCollection commandParameters)
		{
			//if (!LogManager.GetLogger("AccessLog").IsDebugEnabled && !PersistenceProperty.IsLogToDb)
			//{
				action();
				return;
			//}
			//LogDataAccessEntity logEntity = GetLogEntity(action, commandText, commandParameters);
			//if (logEntity == null)
			//{
			//	return;
			//}
			//if (PersistenceProperty.IsLogToDb)
			//{
			//	ThreadPool.QueueUserWorkItem(delegate (object obj)
			//	{
			//		LogDataAccessEntity logDataAccessEntity = obj as LogDataAccessEntity;
			//		string collName = GetChanelConfig() + "Access";
			//		IMongoAccess<LogDataAccessEntity> mongoAccess = DataAccessFactory.Instance.CreateDataAccess<LogDataAccessEntity>(collName);
			//		try
			//		{
			//			if (mongoAccess == null)
			//			{
			//				WriteFile(logDataAccessEntity);
			//			}
			//			else
			//			{
			//				mongoAccess.Open();
			//				mongoAccess.Insert(logDataAccessEntity);
			//			}
			//		}
			//		catch
			//		{
			//			if (logDataAccessEntity != null)
			//			{
			//				string message = string.Format("Ce:{0}{1}Tt:{2}{1}P:{3}{1}T:{4}MS{1}C:{5}", logDataAccessEntity.DbType, Environment.NewLine, logDataAccessEntity.Content, logDataAccessEntity.Params, logDataAccessEntity.WatchTime, logDataAccessEntity.ResultCount);
			//				//LogManager.GetLogger("AccessLog").Debug(message);
			//			}
			//		}
			//		finally
			//		{
			//			mongoAccess?.Dispose();
			//		}
			//	}, logEntity);
			//}
			//else
			//{
			//	string message2 = string.Format("Ce:{0}{1}Tt:{2}{1}P:{3}{1}T:{4}MS{1}C:{5}", logEntity.DbType, Environment.NewLine, logEntity.Content, logEntity.Params, logEntity.WatchTime, logEntity.ResultCount);
			//	//LogManager.GetLogger("AccessLog").Debug(message2);
			//}
		}

        protected void LogOutPut(Func<Task<int>> action, string type, string? commandText, QueryParameterCollection commandParameters)
        { 
            action();
            return; 
        }

        private LogDataAccessEntity GetLogEntity(Func<int> action, string commandText, QueryParameterCollection commandParameters)
		{
			int num = 0;
			Stopwatch stopwatch = Stopwatch.StartNew();
			stopwatch.Start();
			LogDataAccessEntity result;
			try
			{
				num = action();
			}
			finally
			{
				stopwatch.Stop();
				string text = string.Empty;
				if (commandParameters != null)
				{
					for (int i = 0; i < commandParameters.Count; i++)
					{
						text = ((commandParameters[i].Value != null) ? string.Concat(text, commandParameters[i].Value, "|") : (text + "NULL|"));
					}
				}
				LogDataAccessEntity logDataAccessEntity = new LogDataAccessEntity();
				logDataAccessEntity.Content = commandText;
				logDataAccessEntity.DbType = DatabaseType.ToString();
				logDataAccessEntity.Params = text;
				logDataAccessEntity.ResultCount = num;
				logDataAccessEntity.WatchTime = stopwatch.Elapsed.ToString();
				logDataAccessEntity.CurrentTime = DateTime.Now;
				result = logDataAccessEntity;
			}
			return result;
		}

		private void WriteFile(LogDataAccessEntity logentity)
		{
			string message = string.Format("Ce:{0}{1}Tt:{2}{1}P:{3}{1}T:{4}MS{1}C:{5}", logentity.DbType, Environment.NewLine, logentity.Content, logentity.Params, logentity.WatchTime, logentity.ResultCount);
			//LogManager.GetLogger("AccessLog").Debug(message);
		}

		//private string GetChanelConfig()
		//{
			//string configurationFile = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
			//int index = 0;
			//if (File.Exists(configurationFile))
			//{
			//	XmlDocument xmlDocument = new XmlDocument();
			//	xmlDocument.Load(configurationFile);
			//	XmlNode xmlNode = xmlDocument.SelectSingleNode("/configuration/MsgConfiguration/MsgConfigurationData/IpIndex");
			//	if (xmlNode != null)
			//	{
			//		index = Convert.ToInt32(xmlNode.LastChild.Value);
			//	}
			//}
			//IPAddress hostIP = GetHostIP(index);
			//string text = hostIP.ToString().Replace('.', 'P');
			//string configurationFile2 = AppDomain.CurrentDomain.SetupInformation.ConfigurationFile;
			//string text2 = "";
			//if (File.Exists(configurationFile2))
			//{
			//	XmlDocument xmlDocument2 = new XmlDocument();
			//	xmlDocument2.Load(configurationFile2);
			//	XmlNode xmlNode2 = xmlDocument2.SelectSingleNode("configuration/system.runtime.remoting/application/channels/channel");
			//	if (xmlNode2 != null && xmlNode2.Attributes != null)
			//	{
			//		foreach (XmlNode attribute in xmlNode2.Attributes)
			//		{
			//			if ("port" == attribute.Name)
			//			{
			//				text2 += attribute.Value;
			//				text = text + "D" + text2;
			//			}
			//		}
			//	}
			//}
			//return text;
		//}

		private IPAddress GetHostIP(int index)
		{
			IPAddress result = null;
			IPAddress[] addressList = Dns.GetHostEntry(Dns.GetHostName()).AddressList;
			if (addressList.Length > index && addressList[index].AddressFamily == AddressFamily.InterNetwork)
			{
				return addressList[index];
			}
			IPAddress[] array = addressList;
			foreach (IPAddress iPAddress in array)
			{
				if (iPAddress.AddressFamily == AddressFamily.InterNetwork)
				{
					result = iPAddress;
				}
			}
			return result;
		}

		public abstract void FillingTables(List<TableInfo>? info);

		public abstract void FillingColumns(List<ColumnInfo> info);

		public abstract void FillingIndexs(List<IndexInfo>? info);

		public abstract void FillingRelations(List<RelationshipInfo>? info);

		public abstract void FillingViews(List<ViewInfo> info);

		public abstract void FillingProcs(List<ProcInfo> info);

		public abstract void FillingProcParams(List<ProcParamInfo> info);

		public abstract void FillingTypeInfos(List<TypeNameInfos> info);
	}
}